package com.passion.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.passion.bean.OfflineAnalyseResult;
import com.passion.bean.OfflineAnalysisTemplateSqlTable;
import com.passion.exception.TaskTypeDataException;
import com.passion.mapper.OfflineAnalyseResultMapper;
import com.passion.service.OfflineAnalysisTemplateSqlTableService;
import com.passion.mapper.OfflineAnalysisTemplateSqlTableMapper;
import com.passion.utils.DateTimeUtil;
import com.passion.utils.UUIDUtils;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.*;
import static com.passion.enums.CalculateStatus.DIRECT_CALCULATION_GET_RESULTS;
import static com.passion.enums.CalculateStatus.LOAD_HISTORY_CALCULATION_RESULTS;
import static com.passion.enums.ExceptionCode.TYPE_ERROR;
import static com.passion.utils.DateTimeUtil.*;
import static com.passion.utils.ExecuteSqlUtil.*;

/**
 * @author 86151
 * @description 针对表【offline_analysis_template_sql_table】的数据库操作Service实现
 * @createDate 2024-09-28 18:43:48
 */
@Log4j
@Service
public class OfflineAnalysisTemplateSqlTableServiceImpl extends ServiceImpl<OfflineAnalysisTemplateSqlTableMapper, OfflineAnalysisTemplateSqlTable>
        implements OfflineAnalysisTemplateSqlTableService {
    @Autowired
    private OfflineAnalysisTemplateSqlTableMapper offlineAnalysisTemplateSqlTableMapper;

    @Autowired
    private ThreadPoolExecutor poolExecutor;

    @Autowired
    private OfflineAnalyseResultMapper offlineAnalyseResultMapper;

    @Autowired
    private ExecutorService executorService;

    /**
     * 执行离线分析任务
     *
     * @param req
     */

    @Override
    public String executeAnalysis(Map<String, Object> req) {
        String analyseResult = "";
        Object type = req.get("type");
        Object paramsObject = req.get("params");
        Map<String, String> params = (Map<String, String>) paramsObject;
        String sqlID = params.get("sqlID");
        String taskID = UUIDUtils.generateUUID(params);
        params.remove("sqlID");
        // 如果没有传入日期，默认为昨天
        QueryWrapper<OfflineAnalyseResult> queryWrapper = new QueryWrapper<OfflineAnalyseResult>().eq("sql_id", sqlID).eq("task_id", taskID);
        OfflineAnalyseResult result = offlineAnalyseResultMapper.selectOne(queryWrapper);
        OfflineAnalysisTemplateSqlTable job = offlineAnalysisTemplateSqlTableMapper.selectOne(new QueryWrapper<OfflineAnalysisTemplateSqlTable>().eq("sql_id", sqlID));
        String sqlContent = job.getSqlContent();
        if (LOAD_HISTORY_CALCULATION_RESULTS.getStatus().equals(type)) {
            // 如果在结果表中没有对应是sqlID的结果，则执行sql语句
            if (result == null) {
                analyseResult = getResult(sqlContent, params);
                // 将结果存入结果表
                offlineAnalyseResultMapper.insert(new OfflineAnalyseResult(taskID, sqlID, analyseResult));
            } else {
                analyseResult = result.getAnalyseResult();
            }
        } else if (DIRECT_CALCULATION_GET_RESULTS.getStatus().equals(type)) {
            // 删除对应结果表中的结果，执行sql（为修改sql逻辑重新获取分析结果）
            QueryWrapper<OfflineAnalyseResult> queryWrapperDel = new QueryWrapper<OfflineAnalyseResult>().eq("sql_id", sqlID).eq("task_id", taskID);
            offlineAnalyseResultMapper.delete(queryWrapperDel);
            analyseResult = getResult(sqlContent, params);
            log.info("analyseResult" + analyseResult);
            // 将结果存入结果表
            offlineAnalyseResultMapper.insert(new OfflineAnalyseResult(taskID, sqlID, analyseResult));
        } else {
            throw new TaskTypeDataException(TYPE_ERROR);
        }
        return analyseResult;
    }

    /**
     * 触发执行并解析参数
     *
     * @param job
     * @return
     */
    public String triggerExecute(OfflineAnalysisTemplateSqlTable job) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("type", DIRECT_CALCULATION_GET_RESULTS.getStatus());
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("sqlID", job.getSqlId());
        map.put("params", hashMap);
        return executeAnalysis(map);
    }

    /**
     * 异步执行任务
     *
     * @param job
     */
    @Override
    public void executeAnalysisAsync(OfflineAnalysisTemplateSqlTable job) {
        // 解析参数
        poolExecutor.submit(() -> {
            try {
                triggerExecute(job);
            } catch (TaskTypeDataException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 异步获取分析结果
     *
     * @param job
     * @return
     */
    @Override
    public String executeAnalysisAsyncWithResult(OfflineAnalysisTemplateSqlTable job) {
        String result = null;
        try {
            result = CompletableFuture.supplyAsync(() -> {
                // 解析参数触发计算
                return triggerExecute(job);
            }, executorService).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        // 装配结果返回分析结果
        return result;
    }

    /**
     * 执行所有分析sql任务
     */
    @Override
    public void executeEverydayAnalysis() {
        QueryWrapper<OfflineAnalysisTemplateSqlTable> queryWrapper = new QueryWrapper<>();
        List<OfflineAnalysisTemplateSqlTable> jobs = offlineAnalysisTemplateSqlTableMapper.selectList(queryWrapper);
        jobs.forEach(this::executeAnalysisAsync);
    }
}




